package com.unitd.frame.mybatis.core.service.impl;

import com.github.pagehelper.PageInfo;
import com.unitd.frame.mybatis.core.dao.IBaseDao;
import com.unitd.frame.mybatis.core.service.IBaseService;
import com.unitd.frame.mybatis.plugin.page.IPageDataLoader;
import com.unitd.frame.mybatis.plugin.page.PageTemplate;

import java.lang.reflect.Method;
import java.util.List;

/**
 * @desc BaseService 的实现类,其他的自定义 ServiceImpl,继承自它,可以获得常用的增删查改操作,未实现的方法由子类各自实现
 * @param <Model> 代表数据库中的表 映射的Java对象类型
 * @param <PK> 对象的主键类型
 * @filename BaseServiceImpl.java
 * @copyright www.unitd.com
 * @author Hudan
 * @version 1.0
 * @date 2017/2/22
 */
public abstract class BaseServiceImpl<Model, PK> implements IBaseService<Model, PK>, IPageDataLoader<Model> {

	/**
	 * @desc 定义成抽象方法,由子类实现,完成dao的注入
	 * @return GenericDao实现类
	 */
	protected abstract IBaseDao<Model, PK> getDao();

	/**
	 * @desc 保存(持久化)对象(完全保存)
	 * @param entity 要持久化的对象
	 */
	@Override
	public int insert(Model entity) {
		return getDao().insert(entity);
	}

	/**
	 * @desc 保存(持久化)对象(非空字段保存, 空字段按照默认值)
	 * @param entity 要持久化的对象
	 */
	@Override
	public int insertSelective(Model entity) {
		return getDao().insertSelective(entity);
	}

	/**
	 * @desc 批量保存(持久化)对象(完全保存)
	 * @param models 要持久化的对象列表
	 */
	@Override
	public int batchInsert(List<Model> models) {
		int result = 0;
		try {
			for(Model model : models) {
				// 保存持久化的对象数据到数据库中
				result += getDao().insert(model);
			}
			return result;
		} catch (Exception e) {
			throw new RuntimeException(e.getMessage());
		}
	}

	/**
	 * @desc 批量保存(持久化)对象(非空字段保存,空字段按照默认值)
	 * @param models 要持久化的对象列表
	 */
	@Override
	public int batchInsertSelective(List<Model> models) {
		int result = 0;
		try {
			for(Model model : models) {
				// 保存持久化的对象数据到数据库中
				result += getDao().insertSelective(model);
			}
			return result;
		} catch (Exception e) {
			throw new RuntimeException(e.getMessage());
		}
	}

	/**
	 * @desc 根据指定的唯一标识符删除持久化对象
	 * @param id 指定的唯一标识符
	 */
	@Override
	public int deleteByPrimaryKey(PK id) {
		return getDao().deleteByPrimaryKey(id);
	}

	/**
	 * @desc 根据指定的唯一标识符列表,批量删除持久化对象
	 * @param ids 指定的唯一标识符列表
	 */
	@Override
	public int batchDeleteByPrimaryKey(List<PK> ids) {
		int result = 0;
		for(PK id : ids) {
			result += getDao().deleteByPrimaryKey(id);
		}
		return result;
	}

	/**
	 * @desc 更新(持久化)对象
	 * @param entity (持久化)对象
	 */
	@Override
	public int updateByPrimaryKey(Model entity) {
		return getDao().updateByPrimaryKey(entity);
	}

	/**
	 * @desc 更新(持久化)对象
	 * @param entity (持久化)对象
	 */
	@Override
	public int updateByPrimaryKeySelective(Model entity) {
		return getDao().updateByPrimaryKeySelective(entity);
	}

	/**
	 * @desc 批量更新(持久化)对象(完全更新)
	 * @param models 要持久化的对象列表
	 */
	@Override
	public int batchUpdateByPrimaryKey(List<Model> models) {
		int result = 0;
		try {
			for(Model model : models) {
				// 保存持久化的对象数据到数据库中
				result += getDao().updateByPrimaryKey(model);
			}
			return result;
		} catch (Exception e) {
			throw new RuntimeException(e.getMessage());
		}
	}

	/**
	 * @desc 批量更新(持久化)对象(非空字段更新,空字段按照默认值)
	 * @param models 要持久化的对象列表
	 */
	@Override
	public int batchUpdateByPrimaryKeySelective(List<Model> models) {
		int result = 0;
		try {
			for(Model model : models) {
				// 保存持久化的对象数据到数据库中
				result += getDao().updateByPrimaryKeySelective(model);
			}
			return result;
		} catch (Exception e) {
			throw new RuntimeException(e.getMessage());
		}
	}

	/**
	 * @desc 获取指定的唯一标识符对应的持久化对象
	 * @param id 指定的唯一标识符
	 * @return 指定的唯一标识符对应的持久化对象，如果没有对应的持久化对象，则返回null。
	 */
	@Override
	public Model selectByPrimaryKey(PK id) {
		return getDao().selectByPrimaryKey(id);
	}

	/**
	 * @desc 获取指定条件对应的持久化对象
	 * @param model 查询条件
	 * @return 指定的唯一标识符对应的持久化对象，如果没有对应的持久化对象，则返回null。
	 */
	@Override
	public Model selectByBean(Model model) {
		return getDao().selectOne(model);
	}

	/**
	 * @desc 获取指定条件对应的持久化对象的记录条数
	 * @param model 查询条件
	 * @return 记录条数
	 */
	@Override
	public int selectCountByExample(Object model) {
		return getDao().selectCountByExample(model);
	}


	/**
	 * @desc 获取指定条件对应的持久化对象列表
	 * @param param 查询条件
	 * @return 指定的唯一标识符对应的持久化对象，如果没有对应的持久化对象，则返回null。
	 */
	@Override
	public List<Model> selectByExample(Object param) {
		return getDao().selectByExample(param);
	}

	/**
	 * @desc 根据指定查询条件,获取对应的记录列表
	 * @param model 查询条件
	 * @return 指定持久对象的所有 记录,如果没有对应的持久化对象，则返回null。
	 */
	@Override
	public List<Model> listByBean(Model model) {
		return getDao().select(model);
	}

	/**
	 * @desc 获取所有记录
	 * @return 指定持久对象的所有 记录,如果没有对应的持久化对象，则返回null。
	 */
	@Override
	public List<Model> listAll() {
		return getDao().selectAll();
	}

	/**
	 * @desc 加载分页数据
	 * @return 分页数据
	 */
	@Override
	public List<Model> load() {
		return getDao().selectAll();
	}

	/**
	 * @desc 查询分页数据
	 * @param pageNo 当前页数
	 * @param pageSize 每页记录数
	 * @return PageInfo
	 */
	@Override
	public PageInfo<Model> getPageData(int pageNo, int pageSize) {
		return PageTemplate.execute(pageNo, pageSize, () -> getDao().selectAll());
	}

	/**
	 * @desc 查询分页数据
	 * @param pageNo 当前页数
	 * @param pageSize 每页记录数
	 * @param model 查询条件
	 * @return PageInfo
	 */
	@Override
	public PageInfo<Model> getPageData(int pageNo, int pageSize, final Model model) {
		return PageTemplate.execute(pageNo, pageSize, () -> getDao().select(model));
	}

	/**
	 * @desc 查询分页数据,实际查询调用指定的方法
	 * @param pageNo 当前页数
	 * @param pageSize 每页记录数
	 * @param model 查询条件
	 * @param  methodName 需要进行反射处理的数据操作方法
	 * @return PageInfo
	 */
	@Override
	public PageInfo<Model> getPageData(int pageNo, int pageSize, final Model model, final String methodName) {
		return PageTemplate.execute(pageNo, pageSize, () -> {
			try {
				Class clazz = getDao().getClass();
				Method getMethod = clazz.getDeclaredMethod(methodName, model.getClass());
				return (List<Model>) getMethod.invoke(getDao(), model);
			} catch (Exception e) {
				e.printStackTrace();
			}
			return null;
		});
	}
}